const Dnode = require('./dnode');

class DoublyLinkedList {
    // 构造器
    constructor(head = new Dnode()) {
        this.head = head
    }
    // 数组构造
    static createbyArr(arr) {
        let dll = new DoublyLinkedList()
        let p = dll.head
        for (let i = 0; i <= arr.length - 1; i++) {
            p.next = new Dnode(arr[i], p, null)
            p = p.next
        }
        return dll
    }
    // 返回描述字符串
    toString() {
        let str = ""
        let p = this.head
        while (p.next !== null) {
            str += `${p.toString()}<-->`
            p = p.next
        }
        return `${str}${p.toString()}-->`
    }
    // 返回表长
    listSize() {
        let count = 0
        let p = this.head
        while (p.next != null) {
            count++
            p = p.next
        }
        return count
    }
    // 判空
    isEmpty() {
        return this.head.next === null
    }
    // 清空链表
    clear() {
        this.head.next = null
    }
    // get
    getElem(n) {
        if (n <= 0) {
            throw new Error('下越界')
        }
        if (n > this.listSize()) {
            throw new Error('上越界')
        }
        let p = this.head
        for (let i = 0; i <= n - 1; i++) {
            p = p.next
        }
        return p
    }
    // set
    setElem(n, data) {
        if (n <= 0) {
            throw new Error('下越界')
        }
        if (n > this.listSize()) {
            throw new Error('上越界')
        }
        if (data === null || data === undefined) {
            throw new Error('data值不能为null或undefined')
        }
        let p = this.getElem(n)
        p.data = data
    }
    // 值查找
    searchEqual(key) {
        let p = this.head
        while (p !== null && p.data !== key) {
            p = p.next
        }
        return p
    }
    // 插入
    insert(n, data, flag = true) {
        if (n <= 0) {
            n = 1
        }
        if (n > this.listSize() + 1) {
            n = this.listSize()
        }

        let p = this.getElem(n)
        if (flag) {
            let newNode = new Dnode(data, p.prev, p)
            p.prev.next = newNode
            p.prev = newNode
        } else {
            let newNode = new Dnode(data, p, p.next)
            if (n != this.listSize()) {
                p.next.prev = newNode
                p.next = newNode
            } else {
                p.next = newNode
            }
        }
    }
    // 头插入
    headInsert(data) {
        this.insert(Number.MAX_VALUE * (-1), data)
    }
    // 尾插入
    endInsert(data) {
        this.insert(Number.MAX_VALUE, data, false)
    }
    // 删除
    delete(n) {
        if (n <= 0) {
            throw new Error('下越界')
        }
        if (n > this.listSize()) {
            throw new Error('上越界')
        }
        let p = this.getElem(n)
        if (p.next !== null) {
            p.prev.next = p.next
            p.next.prev = p.prev
        } else {
            p.prev.next = null
        }
    }
}

module.exports = DoublyLinkedList





// 测试用例
// let arr = [1, 2, 3, 4, 5, 6]
// let dll = DoublyLinkedList.createbyArr(arr)
// dll.delete(3)
// console.log(dll.toString());